// Copyright (C) 2024 Kumo inc.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <chrono>

#include <ktest/ktest.h>

#include <deneb/lru.h>

TEST(WrapTest, CanWrapMutableAndNonMutableLambdas) {
  // This is purely to make sure both variants compile
  deneb::wrap([](int x) { return x; })(5);
  deneb::wrap([](int x) mutable { return x; })(5);
}

TEST(WrapTest, WrappingWorks) {
  auto f = [x = 0](int _) mutable {
    return ++x;
  };
  auto wrapped = deneb::wrap(f);

  EXPECT_EQ(wrapped(69), 1);
  EXPECT_EQ(wrapped(69), 1);
  EXPECT_EQ(wrapped(42), 2);
  EXPECT_EQ(wrapped(42), 2);
  EXPECT_EQ(wrapped(50), 3);
}

TEST(WrapTest, CanPassCapacityArgumentToWrap) {
  std::size_t call_count = 0;
  auto f = [&call_count](int _) { return call_count += 1; };

  auto wrapped1 = deneb::wrap(f, 1);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);

  auto wrapped2 = deneb::wrap(f, 0);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);
}


TEST(WrapTest, CanPassTimeArgumentToTimedCacheWrap) {
  using namespace std::chrono_literals;

  std::size_t call_count = 0;
  auto f = [&call_count](int _) { return call_count += 1; };

  auto wrapped1 = deneb::wrap<decltype(f), deneb::TimedCache>(f, 100ms);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);

  auto wrapped2 = deneb::timed_wrap(f, 0ms);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);

  wrapped1(1);
  EXPECT_EQ(call_count, 1);
}
